﻿using System;
using System.Collections;
using System.Collections.Generic;

namespace FunctionalProgramming.LazyCollections
{
   /// <summary>
   /// Lazy collection.
   /// </summary>
   /// <typeparam name="T">Type of elements in resulting collection.</typeparam>
   /// <typeparam name="TEval">Type of data that will be evaluated.</typeparam>
   internal class LazyEnumerable<T, TEval> : IEnumerable<T>
   {
      /// <summary>
      /// Initializes a new instance of the <see cref="LazyEnumerable&lt;T, TEval&gt;"/> class.
      /// </summary>
      /// <param name="evaluator">The evaluation function.</param>
      /// <param name="initialEvaluatorValue">The initial value to be evaluated.</param>
      public LazyEnumerable(Func<TEval, Option<T, TEval>> evaluator, TEval initialEvaluatorValue)
      {
         Evaluator = evaluator;
         InitialEvaluatorValue = initialEvaluatorValue;
      }

      /// <summary>
      /// Gets the enumerator.
      /// </summary>
      /// <returns></returns>
      public IEnumerator<T> GetEnumerator()
      {
         return new LazyEnumerator<T, TEval>(this);
      }

      /// <summary>
      /// Returns an enumerator that iterates through a collection.
      /// </summary>
      /// <returns>
      /// An <see cref="T:System.Collections.IEnumerator"/> object that can be used to iterate through the collection.
      /// </returns>
      IEnumerator IEnumerable.GetEnumerator()
      {
         return GetEnumerator();
      }

      /// <summary>
      /// Gets the evaluator.
      /// </summary>
      public Func<TEval, Option<T, TEval>> Evaluator { get; private set; }

      /// <summary>
      /// Gets the initial evaluator value.
      /// </summary>
      public TEval InitialEvaluatorValue { get; private set; }
   }
}